// C++ Templates: 第13.3节 解析模板
// 第13.3节"解析模板"(Parsing Templates)主要讨论了C++编译器如何解析模板代码，以及在这个过程中可能遇到的各种挑战和歧义。这是理解模板行为的重要基础。

// 13.3 解析模板的核心内容
// 解析挑战
// C++模板的解析是复杂的，主要因为：
// 1.语法歧义：某些语法结构可能有多种解释
// 2.依赖名称：依赖于模板参数的名称在实例化前无法完全解析
// 3.两阶段查找：编译器需要在不同阶段进行名称查找

// 尖括号问题
// 最经典的解析问题是"尖括号问题"：
std::vector<std::vector<int>> v; // C++11前需要空格: std::vector<std::vector<int> >
// 在C++11之前，连续的关闭尖括号>>会被解析为右移运算符，需要添加空格避免歧义。C++11修复了这个问题。

// 模板中的表达式解析
// 模板参数中的表达式解析也存在挑战：
template <bool B>
class MyClass
{
    // ...
};

MyClass<sizeof(int) < 4> mc; // 歧义：是 MyClass<(sizeof(int) < 4)> 还是 MyClass<sizeof(int)> < 4 ?
// 编译器会将其解析为MyClass<(sizeof(int) < 4)>，但这种写法容易引起混淆。

// 依赖名称的解析
// 依赖名称的解析需要特殊处理：
template <typename T>
void func()
{
    T::template create<int>(); // 需要template关键字
    typename T::type var;      // 需要typename关键字
}
// 这些关键字告诉编译器如何正确解析依赖名称。

// 类型与非类型的歧义
// 在某些情况下，编译器难以区分类型和非类型名称：
template <typename T>
void func()
{
    T::x *ptr; // 歧义：是声明指针还是乘法表达式？
}
// 使用typename解决歧义
// typename关键字用于指明依赖名称是一个类型：
template <typename T>
void func()
{
    typename T::x *ptr; // 明确指出T::x是一个类型
}

// 模板模板参数的解析
// 模板模板参数的解析也需要特殊处理：
template <template <typename> class Container>
class Adapter
{
    Container<int> container; // 使用模板模板参数
};

// 嵌套模板的特殊语法
// 在依赖上下文中使用嵌套模板需要特殊语法：
template <typename T>
void func()
{
    // 告诉编译器T::template create是一个模板
    T::template create<int>();

    // 不需要template关键字的情况
    typename T::template create<int>::type var; // typename已经表明这是一个类型
}

// 实际应用示例
// 标准库中的例子
template <typename Iterator>
void algorithm(Iterator first, Iterator last)
{
    // 使用typename指明这是一个类型
    typename std::iterator_traits<Iterator>::value_type temp;

    // 使用
    for (Iterator it = first; it != last; ++it)
    {
        // 处理...
    }
}

// 解析技巧和最佳实践
// 1.使用括号消除歧义：
MyClass<(sizeof(int) < 4)> mc; // 使用括号明确优先级

// 2.适当使用typename和template关键字：
typename T::type var;
T::template create<int>();

// 3.避免过度复杂的表达式： 将复杂表达式拆分为更简单的部分，提高可读性
// 4.使用类型别名简化复杂类型：
template <typename T>
using value_type = typename std::iterator_traits<T>::value_type;